#pragma once
#include <iostream>
#include <unistd.h>
#include <pthread.h>
#include <vector>
#include <queue>
#include "Task.hpp"
using std::cout;
using std::endl;
using std::queue;
using std::string;
using std::to_string;
using std::vector;

static const int DefaultNum = 5;
static bool isrunning = true;
static pthread_mutex_t slock = PTHREAD_MUTEX_INITIALIZER;

template <class T>
class ThreadPool
{
private:
    void lock()
    {
        pthread_mutex_lock(&qlock_);
    }

    void unlock()
    {
        pthread_mutex_unlock(&qlock_);
    }

    void Threadawake()
    {
        pthread_cond_signal(&cond_);
    }

    void Threadsleep()
    {
        pthread_cond_wait(&cond_, &qlock_);
    }

public:
    // 线程函数不要直接调用都会自己执行
    static void *ExecTask(void *argv)
    {
        ThreadPool *tp = static_cast<ThreadPool<T> *>(argv);
        string name = to_string(pthread_self());
        while (isrunning)
        {
            tp->lock();
            while (tp->tq_.empty())
            {
                tp->Threadsleep();

                if (isrunning == false)
                //用来防止误唤醒的while里面又让其他线程去条件等待去了
                    break;
            }
            Task t = tp->tq_.front();
            tp->tq_.pop();
            tp->unlock();
            t();
            pthread_mutex_lock(&slock);
            cout << name << ":";
            cout << t.getResult() << endl;
            pthread_mutex_unlock(&slock);
        }
        return nullptr;
    }

    void PushTask(Task &t)
    {
        lock();
        tq_.push(t);
        Threadawake();
        unlock();
    }

    static ThreadPool *getInstance()
    {
        // 不用释放内存，一般会伴随整个进程的生命周期
        if (tp_ == nullptr)
        {
            pthread_mutex_lock(&PLOCK_);
            if (tp_ == nullptr)
            {
                tp_ = new ThreadPool();
            }
            pthread_mutex_unlock(&PLOCK_);
        }
        return tp_;
    }

    static void delInstance()
    {
        if (tp_ != nullptr)
        {
            delete tp_;
            tp_ = nullptr;
        }
    }

    void run(int nums = DefaultNum)
    {
        for (int i = 0; i < nums; i++)
        {
            pthread_t tid;
            pthread_create(&tid, nullptr, ExecTask, this);
            tids_.push_back(tid);
        }
    }

private:
    ThreadPool()
    {
        pthread_mutex_init(&qlock_, nullptr);
        pthread_cond_init(&cond_, nullptr);
    }

    ~ThreadPool()
    {
        isrunning = false;
        pthread_cond_broadcast(&cond_);
        //条件在等待的时候，destroy会堵塞，直到被唤醒为止
        pthread_mutex_destroy(&qlock_);
        pthread_cond_destroy(&cond_);
    }

private:
    ThreadPool(const ThreadPool &pool) = delete;
    ThreadPool &operator=(const ThreadPool &pool) = delete;

    vector<pthread_t> tids_; // 记录线程

    queue<T> tq_; // 共享资源

    pthread_mutex_t qlock_; // 队列锁和条件变量
    pthread_cond_t cond_;

    static ThreadPool *tp_;
    static pthread_mutex_t PLOCK_;
};

template <class T>
ThreadPool<T> *ThreadPool<T>::tp_ = nullptr;

template <class T>
pthread_mutex_t ThreadPool<T>::PLOCK_ = PTHREAD_MUTEX_INITIALIZER;
